package org.fujene.memoryblock.invert;

import java.util.ArrayList;
import org.fujene.constants.Constants;
import org.fujene.memoryblock.BlockPackage;
import org.fujene.structure.LookupPointer;

// invert index package
public final class InvertIndexPackage implements BlockPackage{
	private int newest;
	private long[] contentPtrs;
	private LookupPointer current;
	private boolean[][] binaryFlags;
	private int[][] multiFlags;
	private ArrayList<Integer> deletedIndex;

	private InvertIndexPackage(){}

	public static InvertIndexPackage setPackage(int index, int block, int point){
		InvertIndexPackage pkg = new InvertIndexPackage();
		pkg.current = LookupPointer.valueOf(block, point);
		pkg.contentPtrs = new long[index];
		pkg.binaryFlags = new boolean[index][];
		pkg.multiFlags = new int[index][];
		pkg.deletedIndex = new ArrayList<Integer>();

		return pkg;
	}

	public void current(LookupPointer ptr){
		this.current = ptr;
	}

	public void contentPtr(long content, int index){
		this.contentPtrs[index] = content;
	}

	public void newest(int newest){
		this.newest = newest - 1;
		if(newest == 0) this.newest = Constants.PERUSER - 1;
	}

	public void binaryFlag(boolean[] flags, int index){
		this.binaryFlags[index] = flags;
	}

	public void multiFlag(int[] flags, int index){
		this.multiFlags[index] = flags;
	}

	public long[] getContentPtrs(){
		long[] newarray = new long[length()];
		int count = 0;
		for(int i = newest; i >= 0; i--){
			if(!deletedIndex.contains(Integer.valueOf(i)) || contentPtrs[i] != 0L)
				newarray[count++] = contentPtrs[i];
		}
		if((contentPtrs.length - 1) > newest){
			for(int i = contentPtrs.length; i > newest; i--){
				if(!deletedIndex.contains(Integer.valueOf(i)) || contentPtrs[i] != 0L)
					newarray[count++] = contentPtrs[i];
			}
		}
		return contentPtrs;
	}

	public long getContentPtr(int index){
		if(index >= contentPtrs.length) return Long.MIN_VALUE;
		int actualindex = (index <= newest? newest - index: Constants.PERUSER + newest - index);
		if(deletedIndex.contains(Integer.valueOf(actualindex))) return Long.MIN_VALUE;
		return contentPtrs[actualindex];
	}

	public int getNewest(){
		return newest;
	}

	public LookupPointer getCurrent(){
		return current;
	}

	public boolean[][] getBinaryFlags(){
		return binaryFlags;
	}

	public boolean[] getBinaryFlags(int index){
		int actualindex = (index <= newest? newest - index: Constants.PERUSER + newest - index);
		return binaryFlags[actualindex];
	}

	public boolean getBinaryFlag(int index, int bit){
		int actualindex = (index <= newest? newest - index: Constants.PERUSER + newest - index);
		return binaryFlags[actualindex][bit];
	}

	public int[][] getMultiFlags(){
		return multiFlags;
	}

	public int[] getMultiFlags(int index){
		int actualindex = (index <= newest? newest - index: Constants.PERUSER + newest - index);
		return multiFlags[actualindex];
	}

	public int getMultiFlag(int index, int subindex){
		int actualindex = (index <= newest? newest - index: Constants.PERUSER + newest - index);
		return multiFlags[actualindex][subindex];
	}

	public void delete(int index){
		deletedIndex.add(Integer.valueOf(index));
	}

	public int size(){
		return contentPtrs.length - deletedIndex.size();
	}

	@Override
	public int length(){
		return NEWEST + (LONG * contentPtrs.length);
	}
}